/**
 * 文章控制器
 * @module controllers/articleController
 */

const { Article, Category, Comment, sequelize } = require('../models');
const { Op } = require('sequelize');

/**
 * 获取所有文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const getAllArticles = async (req, res) => {
  try {
    const { page = 1, limit = 10, category, search, published } = req.query;
    const offset = (page - 1) * limit;
    
    // 构建查询条件
    const where = {};
    
    // 如果指定了分类
    if (category) {
      where.categoryId = category;
    }
    
    // 如果指定了发布状态
    if (published !== undefined) {
      where.published = published === 'true';
    } else {
      // 非管理员只能看到已发布的文章
      if (!req.user || req.user.role !== 'admin') {
        where.published = true;
      }
    }
    
    // 如果有搜索关键词
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        { content: { [Op.like]: `%${search}%` } }
      ];
    }
    
    // 查询文章
    const { count, rows: articles } = await Article.findAndCountAll({
      where,
      include: [
        { model: Category, as: 'category', attributes: ['id', 'name'] }
      ],
      order: [['publishDate', 'DESC']],
      limit: parseInt(limit),
      offset: parseInt(offset),
      attributes: { exclude: ['content'] } // 不返回完整内容
    });
    
    return res.status(200).json({
      articles,
      totalPages: Math.ceil(count / limit),
      currentPage: parseInt(page),
      totalItems: count
    });
  } catch (error) {
    console.error('获取文章列表错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 获取单篇文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const getArticleById = async (req, res) => {
  try {
    const { id } = req.params;
    
    // 查询文章
    const article = await Article.findByPk(id, {
      include: [
        { model: Category, as: 'category', attributes: ['id', 'name'] },
        { 
          model: Comment, 
          as: 'comments', 
          where: { approved: true },
          required: false,
          attributes: ['id', 'username', 'content', 'createdAt']
        }
      ]
    });
    
    if (!article) {
      return res.status(404).json({ message: '文章不存在' });
    }
    
    // 非管理员只能看到已发布的文章
    if (!article.published && (!req.user || req.user.role !== 'admin')) {
      return res.status(404).json({ message: '文章不存在' });
    }
    
    // 增加访问量
    await article.increment('views');
    
    return res.status(200).json({ article });
  } catch (error) {
    console.error('获取文章详情错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 创建文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const createArticle = async (req, res) => {
  try {
    const { title, content, excerpt, image, categoryId, tags, published } = req.body;
    
    // 验证请求体
    if (!title || !content || !categoryId) {
      return res.status(400).json({ message: '标题、内容和分类不能为空' });
    }
    
    // 检查分类是否存在
    const category = await Category.findByPk(categoryId);
    if (!category) {
      return res.status(404).json({ message: '分类不存在' });
    }
    
    // 创建文章
    const article = await Article.create({
      title,
      content,
      excerpt: excerpt || content.substring(0, 200),
      image,
      categoryId,
      tags: tags || [],
      published: published || false,
      publishDate: published ? new Date() : null
    });
    
    // 更新分类文章数
    await category.increment('postCount');
    
    return res.status(201).json({ 
      message: '文章创建成功',
      article
    });
  } catch (error) {
    console.error('创建文章错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 更新文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const updateArticle = async (req, res) => {
  const transaction = await sequelize.transaction();
  
  try {
    const { id } = req.params;
    const { title, content, excerpt, image, categoryId, tags, published } = req.body;
    
    // 查找文章
    const article = await Article.findByPk(id);
    if (!article) {
      await transaction.rollback();
      return res.status(404).json({ message: '文章不存在' });
    }
    
    // 如果更改了分类
    if (categoryId && categoryId !== article.categoryId) {
      // 检查新分类是否存在
      const newCategory = await Category.findByPk(categoryId);
      if (!newCategory) {
        await transaction.rollback();
        return res.status(404).json({ message: '分类不存在' });
      }
      
      // 更新旧分类和新分类的文章数
      const oldCategory = await Category.findByPk(article.categoryId);
      if (oldCategory) {
        await oldCategory.decrement('postCount', { transaction });
      }
      await newCategory.increment('postCount', { transaction });
    }
    
    // 如果从未发布变为已发布，设置发布日期
    const isNewlyPublished = !article.published && published;
    
    // 更新文章
    await article.update({
      title: title || article.title,
      content: content || article.content,
      excerpt: excerpt || (content ? content.substring(0, 200) : article.excerpt),
      image: image || article.image,
      categoryId: categoryId || article.categoryId,
      tags: tags || article.tags,
      published: published !== undefined ? published : article.published,
      publishDate: isNewlyPublished ? new Date() : article.publishDate
    }, { transaction });
    
    await transaction.commit();
    
    return res.status(200).json({ 
      message: '文章更新成功',
      article
    });
  } catch (error) {
    await transaction.rollback();
    console.error('更新文章错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 删除文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const deleteArticle = async (req, res) => {
  const transaction = await sequelize.transaction();
  
  try {
    const { id } = req.params;
    
    // 查找文章
    const article = await Article.findByPk(id);
    if (!article) {
      await transaction.rollback();
      return res.status(404).json({ message: '文章不存在' });
    }
    
    // 更新分类文章数
    const category = await Category.findByPk(article.categoryId);
    if (category) {
      await category.decrement('postCount', { transaction });
    }
    
    // 删除文章
    await article.destroy({ transaction });
    
    await transaction.commit();
    
    return res.status(200).json({ message: '文章删除成功' });
  } catch (error) {
    await transaction.rollback();
    console.error('删除文章错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 获取精选文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const getFeaturedArticles = async (req, res) => {
  try {
    // 获取访问量最高的已发布文章
    const articles = await Article.findAll({
      where: { published: true },
      include: [
        { model: Category, as: 'category', attributes: ['id', 'name'] }
      ],
      order: [['views', 'DESC']],
      limit: 5,
      attributes: { exclude: ['content'] }
    });
    
    return res.status(200).json({ articles });
  } catch (error) {
    console.error('获取精选文章错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

/**
 * 搜索文章
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @returns {Object} 响应对象
 */
const searchArticles = async (req, res) => {
  try {
    const { q } = req.query;
    
    if (!q) {
      return res.status(400).json({ message: '搜索关键词不能为空' });
    }
    
    // 构建查询条件
    const where = {
      [Op.or]: [
        { title: { [Op.like]: `%${q}%` } },
        { content: { [Op.like]: `%${q}%` } }
      ],
      published: true
    };
    
    // 查询文章
    const articles = await Article.findAll({
      where,
      include: [
        { model: Category, as: 'category', attributes: ['id', 'name'] }
      ],
      order: [['publishDate', 'DESC']],
      limit: 10,
      attributes: { exclude: ['content'] }
    });
    
    return res.status(200).json({ articles });
  } catch (error) {
    console.error('搜索文章错误:', error);
    return res.status(500).json({ message: '服务器错误' });
  }
};

module.exports = {
  getAllArticles,
  getArticleById,
  createArticle,
  updateArticle,
  deleteArticle,
  getFeaturedArticles,
  searchArticles
}; 